from Bases import BaseObject, setID
from DeviceSystem.Groups.Group import GroupBase

class Stack(BaseObject):
    _saved_class_name = 'Stack'
    _saved_attributes = ['id', 'name']
    _saved_child_objects = ['Snapshots']
    def __init__(self, **kwargs):
        self.MainController = kwargs.get('MainController')
        self.Effects = self.MainController.EffectsSystem
        self._current_index = None
        super(Stack, self).__init__(**kwargs)
        self.register_signal('current_index_changed', 'new_snapshot')
        if 'deserialize' not in kwargs:
            self.id = setID(kwargs.get('id'))
            self.name = kwargs.get('name', '')
            self.Snapshots = {}
        self.snapshots_indexed = {}
        for s in self.Snapshots.itervalues():
            self.snapshots_indexed.update({s.index:s})
        self.current_index = min(self.snapshots_indexed.keys())
            
    @property
    def current_index(self):
        return self._current_index
    @current_index.setter
    def current_index(self, value):
        if value != self._current_index:
            self._current_index = value
            self.next_index = self.find_next_index(value)
            self.emit('current_index_changed', value=value, next=self.next_index)
            
    def find_next_index(self, value):
        keys = self.snapshots_indexed.copy().keys()
        keys.sort()
        i = keys.index(value)
        if len(keys) <= i + 1:
            return keys[i] + 1
        else:
            return keys[i + 1]
            
    def store_snapshot(self, **kwargs):
        objects = kwargs.get('objects', {})
        index = kwargs.get('index')
        if 'objects' in kwargs:
            del kwargs['objects']
        snapshot = self.snapshots_indexed.get(index)
        if not snapshot:
            kwargs.setdefault('MainController', self.MainController)
            snapshot = Snapshot(**kwargs)
            snapshot.connect('index_changed', self.on_snapshot_index_changed)
            self.Snapshots.update({snapshot.id:snapshot})
            self.update_snapshot_index()
            print 'new_snapshot'
            self.emit('new_snapshot', obj=snapshot, id=snapshot.id)
        snapshot.add_member(**objects)
        
    def recall_snapshot(self, **kwargs):
        snapshot = kwargs.get('snapshot')
        id = kwargs.get('id')
        index = kwargs.get('index')
        if not snapshot:
            if id:
                snapshot = self.Snapshots[id]
            elif index:
                snapshot = self.snapshots_indexed[index]
        self.current_index = index
        snapshot.recall_member_values()
        
    def update_snapshot_index(self):
        for key, val in self.Snapshots.iteritems():
            self.snapshots_indexed.update({val.index:val})
            
    def on_snapshot_index_changed(self, **kwargs):
        self.update_snapshot_index()
        
    def _deserialize_child(self, d):
        if d['saved_class_name'] == 'Snapshot':
            return Snapshot(MainController=self.MainController, deserialize=d)

class Snapshot(GroupBase):
    _saved_class_name = 'Snapshot'
    _saved_attributes = ['id', 'name', 'index', 'root_members', 'member_values', 'fade_time']
    def __init__(self, **kwargs):
        self.MainController = kwargs.get('MainController')
        self.Effects = self.MainController.EffectsSystem
        self._fade_time = None
        self._index = None
        self.Devices = {}
        signals = kwargs.get('signals_to_register', [])
        signals += ['fade_time_changed', 'index_changed']
        kwargs.update({'signals_to_register':signals})
        super(Snapshot, self).__init__(**kwargs)
        if 'deserialize' not in kwargs:
            self.id = setID(kwargs.get('id'))
            self.name = kwargs.get('name', '')
            self.index = kwargs.get('index')
            self.root_members = set()
            self.member_values = {}
            self.fade_time = kwargs.get('fade_time', 2)
        self.fader = self.Effects.add_fader(id=self.id)
        members = kwargs.get('members', {})
        all_devs = self.MainController.AllDevices
        for key in self.root_members:
            obj = all_devs.search_for_obj(key)
            if obj:
                members.update({key:obj})
            else:
                bob
        if 'deserialize' in kwargs:
            members.update({'reload_values':True})
        self.add_member(**members)
        
    def unlink(self):
        self.Effects.del_fader(fader=self.fader)
        super(Snapshot, self).unlink()
        
    @property
    def fade_time(self):
        return self._fade_time
    @fade_time.setter
    def fade_time(self, value):
        value = float(value)
        if value != self._fade_time:
            self._fade_time = value
            self.emit('fade_time_changed', value=value, snapshot=self)
    @property
    def index(self):
        return self._index
    @index.setter
    def index(self, value):
        if value != self._index:
            self._index = value
            self.emit('index_changed', value=value)
            
    def add_member(self, **kwargs):
        '''
        :Parameters:
            reload_values : bool, if True, reload member values from dictionary,
                otherwise, use current.  (default is False)
        '''
        reload = kwargs.get('reload_values', False)
        if 'reload_values' in kwargs:
            del kwargs['reload_values']
        for key, val in kwargs.iteritems():
            self.root_members.add(key)
            if getattr(val, 'base_class') == 'Group':
                d = val.get_objects()
                for dkey, dval in d['Device'].iteritems():
                    for group in dval.Groups.itervalues():
                        super(Snapshot, self).add_member(**{group.id:group})
                        self.fader.add_obj(group)
                        if reload:
                            self.reload_member_values(group.id)
                        else:
                            self.store_member_values(group.id)
                    for attrib in dval.Attributes.itervalues():
                        if attrib.captured_by is None:
                            super(Snapshot, self).add_member(**{attrib.id:attrib})
                            self.fader.add_obj(attrib)
                            if reload:
                                self.reload_member_values(attrib.id)
                            else:
                                self.store_member_values(attrib.id)
    
    def old_add_member(self, **kwargs):
        for key, val in kwargs.iteritems():
            if 'Device' in val.saved_class_name and getattr(val, 'base_class') != 'Group':
                self.Devices.update({key:val})
                for attrib in val.Attributes.itervalues():
                    super(Snapshot, self).add_member(**{attrib.id:attrib})
                    if attrib.id not in self.fader.obj_ids:
                        self.fader.add_obj(attrib)
                    self.store_member_values(attrib.id)
            else:
                super(Snapshot, self).add_member(**{key:val})
                if key not in self.fader.obj_ids:
                    self.fader.add_obj(val)
                self.store_member_values(key)
        print self.member_values
    
    def reload_member_values(self, key=None):
        if key is not None and key in self.member_values:
            value = self.member_values[key]
            self.fader.effects['Fade'].store_value(objkey=key, timeV=1.0, value=value)
        else:
            for key, val in self.member_values.iteritems():
                self.fader.effects['Fade'].store_value(objkey=key, timeV=1.0, value=val)
    
    def store_member_values(self, key=None):
        if key:
            member = self.members[key]
            self.member_values.update({key:member.value})
        else:
            for key, member in self.members.iteritems():
                self.member_values.update({key:member.value})
        self.fader.effects['Fade'].store_value(objkey=key, timeV=1.0)
    
    def old_store_member_values(self, key=None):
        if key:
            self.member_values.update({key:self.members[key].value})
        else:
            for key, val in self.members.iteritems():
                self.member_values.update({key:val.value})
    
    def recall_member_values(self):
        self.fader.effects['Fade'].store_value(timeV=0.0)
        self.fader.sequencer.duration = self.fade_time
        self.fader.sequencer.start()
    
    def old_old_recall_member_values(self):
        e = self.fader.effects['Fade']
        for key, val in self.member_values.iteritems():
            if type(val) == dict:
                for ckey, cval in e.controllers[key].iteritems():
                    start = self.members[key].Groups[ckey].value / cval.obj_scale_factor
                    end = self.member_values[key][ckey] / cval.obj_scale_factor
                    cval.add_keyframes({0.0:start, 1.0:end})
                    print key, ckey, cval.keyframes
            else:
                c = e.controllers[key]
                start = self.members[key].value / c.obj_scale_factor
                end = self.member_values[key] / c.obj_scale_factor
                c.add_keyframes({0.0:start, 1.0:end})
        self.fader.sequencer.duration = self.fade_time
        self.fader.sequencer.start()
    
    def old_recall_member_values(self):
        e = self.fader.effects['Fade']
        for key, val in self.member_values.iteritems():
            if type(val) == dict:
                for ckey, cval in e.controllers[key].iteritems():
                    start = self.members[key].value / cval.obj_scale_factor
                    end = self.member_values[key] / cval.obj_scale_factor
                    cval.add_keyframes({0.0:start, 1.0:end})
            else:
                c = e.controllers[key]
                start = self.members[key].value / c.obj_scale_factor
                end = self.member_values[key] / c.obj_scale_factor
                c.add_keyframes({0.0:start, 1.0:end})
        self.fader.sequencer.duration = self.fade_time
        self.fader.sequencer.start()
        
    
